module calc_phase (
  input  wire         clk    , // 系统时钟
  input  wire         rst_n  , // 系统异步复位，低电平有效
  input  wire         vld_in , // 输入数据有效指示
  input  wire [15:0]  x      , // 输入实部数据，二进制补码格式
  input  wire [15:0]  y      , // 输入虚部数据，二进制补码格式
  output wire         vld_out, // 输出数据有效指示
  output wire [15:0]  p        // 输出相位数据，二进制补码定点格式，1位符号整数位，15位小数位，取值范围[-1, 1)
);

// Parameters
localparam IDLE  = 2'd0;
localparam BUSY  = 2'd1;
localparam DONE  = 2'd2;

wire   signed  [17:0]  angle [15:1];
// 基准角度值 pi为单位 且 放大了 100000倍
assign {
angle[1],angle[2], angle[3] ,angle[4] ,angle[5] ,angle[6] ,angle[7] ,angle[8],
angle[9],angle[10],angle[11],angle[12],angle[13],angle[14],angle[15]
} = {
18'sd25000,18'sd14758,18'sd07797,18'sd03958,18'sd01986,18'sd00994,18'sd00497,18'sd00248,
18'sd00124,18'sd00062,18'sd00031,18'sd00015,18'sd00007,18'sd00003,18'sd00001
};

// local signal
reg [1:0] state, state_next;
reg    signed  [30:0]  x_r1         ;
reg    signed  [30:0]  y_r1         ;
reg    signed          o_valid1     ;
reg    signed  [17:0]  angle_remain;
reg    signed  [1 :0]  quadrant_r  ;
reg    d;//1为+ 0为-
reg    [3:0]   counter;

// FSM
always @ (posedge clk or negedge rst_n) begin
  if (!rst_n)
      state <= IDLE;
  else
      state <= state_next;
end

always @ (*) begin
  case (state)
      IDLE: state_next = vld_in  ? BUSY : IDLE;
      BUSY: state_next = counter==14 ? DONE : BUSY;
      DONE: state_next =           IDLE ;
      default: state_next = IDLE;
  endcase
end

// 象限标记
wire quadrant_1 = ~x[15]&~y[15];
wire quadrant_2 = x[15]&~y[15];
wire quadrant_3 = x[15]&y[15];
wire quadrant_4 = ~x[15]&y[15];
// idle
always @(posedge clk or negedge rst_n) begin
  if (~rst_n) begin
    x_r1       <= 0;
    y_r1       <= 0;
    quadrant_r <= 0;
  end
  else begin
    case (state)
    IDLE : if (vld_in) begin
      x_r1       <= {({16{quadrant_1}} & x  | {16{quadrant_2}} & -x
                  | {16{quadrant_3}} & -x   | {16{quadrant_4}} & x),15'b0};
      y_r1       <= {y,15'b0} ;
      quadrant_r <= {2{quadrant_1}} & 2'b00 | {2{quadrant_2}} & 2'b01
                  | {2{quadrant_3}} & 2'b10 | {2{quadrant_4}} & 2'b11;
      angle_remain <= 0;
    end
    BUSY : begin
      if (~y_r1[30]) begin
        x_r1       <= x_r1 + (y_r1>>>counter);
        y_r1       <= y_r1 - (x_r1>>>counter);
        angle_remain <= angle_remain + angle[counter+1];
      end
      else begin
        x_r1       <= x_r1 - (y_r1>>>counter);
        y_r1       <= y_r1 + (x_r1>>>counter);
        angle_remain <= angle_remain - angle[counter+1];
      end
    end
    default : ;
    endcase
  end
end

always @(posedge clk or negedge rst_n) begin
  if (~rst_n) begin
    counter <= 0;
  end
  else if (state==IDLE && state_next==BUSY) begin
    counter <= 0;
  end
  else if (state==BUSY) begin
    counter <= counter + 1;
  end
end

assign vld_out = state==DONE;
wire [17:0] p_t = vld_out ? (
               {18{quadrant_r==2'b00}} & angle_remain           
              |{18{quadrant_r==2'b01}} & (18'sd100000-angle_remain)
              |{18{quadrant_r==2'b10}} & (-18'sd100000-angle_remain)
              |{18{quadrant_r==2'b11}} & angle_remain           
              ) : 0;
assign p = p_t[17:2];
// 角度放大倍数 * 100000 / 4

endmodule